/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "ui数值部件.h"
#include "ui标量部件.h"

#include "core/属性.h"
#include "core/shader_binding_ID.h"
#include "core/shader_curve.h"
#include "core/引擎配置.h"
#include "core/动画/curve.h"

#include "底层绘图/intern/绘图框架.h"
#include "UI/UI.h"


static uint16 g滚动条变换绘制ID = 0;
static uint16 g滚动条颜色绘制ID = 0;
static uint16 g滚动条边颜色绘制ID = 0;



static float32 g_手臂越界距离 = 0.0f;



static bool on_手柄按键按下(C_Widget* self, const E_鼠标按钮& 按钮) {

	return true;
}

static vec2 g鼠标位置偏移记录;
static E_事件是否传递 on_数值滚动条手柄开始拖拽(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	C_滚动条* 滚动条 = dynamic_cast<C_滚动条*>(self->m_父部件);
	滚动条->m_拖放阻止鼠标进出事件 = true;
	data.m_Type = E_拖放数据类型::e_鼠标拖放_滚动条;
	data.m_Next = self;
	
	g鼠标位置偏移记录 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_数值滚动条手柄拖动(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	if(data.m_Type != E_拖放数据类型::e_鼠标拖放_滚动条 || data.m_Next != self) return E_事件是否传递::e_事件传递_继续;

	C_滚动条* 滚动条 = dynamic_cast<C_滚动条*>(self->m_父部件);
	float32 滚动条在条中比例 = 0;

	vec2 鼠标位置 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, 滚动条);

	if (滚动条->m_排列方向 == E_方向::e_纵向) {
		self->f_setY(鼠标位置.y - g鼠标位置偏移记录.y);
		if (self->m_Pos.y < 0) self->f_setY(0);
		else if (self->m_Pos.y + self->m_Size.y > 滚动条->m_Size.y) self->m_Pos.y = 滚动条->m_Size.y - self->m_Size.y;

		滚动条在条中比例 = self->m_Pos.y / (滚动条->m_Size.y - self->m_Size.y + 0.00000001);
		//std::cout << "(*m_滚动条->m_Size.y - self->m_Size.y) = " << self->m_Pos.y << "  " << 滚动条->m_Size.y - self->m_Size.y << std::endl;
	}
	else {
		self->f_setX(鼠标位置.x - g鼠标位置偏移记录.x);
		if (self->m_Pos.x < 0) self->f_setX(0);
		else if (self->m_Pos.x + self->m_Size.x > 滚动条->m_Size.x) self->m_Pos.x = 滚动条->m_Size.x - self->m_Size.x;

		滚动条在条中比例 = self->m_Pos.x / (滚动条->m_Size.x - self->m_Size.x + 0.00000001);
	}

	滚动条->f_计算绑定的值(滚动条在条中比例);
	滚动条->m_父部件->m_更新绘制属性 = true;
	if (滚动条->mf_滑块滚动回调) 滚动条->mf_滑块滚动回调(滚动条, 滚动条->f_getValue());
	return E_事件是否传递::e_事件传递_终止;
}

static bool on_数值滚动条手柄结束拖拽(C_Widget* self, C_Widget* 拾取的部件, S_拖放数据& data) {
	C_滚动条* 滚动条 = dynamic_cast<C_滚动条*>(self->m_父部件);
	if (滚动条->m_排列方向 == E_方向::e_纵向) {
		if (self->m_Pos.y < 0) self->f_setY(0);
	}
	else {
		if (self->m_Pos.x < 0) self->f_setX(0);
	}
	滚动条->m_拖放阻止鼠标进出事件 = false;
	滚动条->m_滑块->m_ColorA.m_颜色.a = S_UI主题::uic_滚动条按钮.a;
	//鼠标位置记录.x += self->m_GlobalLoc.x + C_Widget::g_鼠标.相对窗口偏移.x;
	//鼠标位置记录.y += self->m_GlobalLoc.y + C_Widget::g_鼠标.相对窗口偏移.y;
	滚动条->m_更新绘制属性 = true;
	g鼠标位置偏移记录 = {};
	return true;
}


E_事件是否传递 on_单向滚动条鼠标进入(C_Widget* self, const S_鼠标& 鼠标) {
	C_滚动条* 滚动条 = dynamic_cast<C_滚动条*>(self);
	滚动条->m_滑块->m_ColorA.m_颜色.a = 255;
	滚动条->m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_终止;
}
E_事件是否传递 on_单向滚动条鼠标离开(C_Widget* self, const S_鼠标& 鼠标) {
	C_滚动条* 滚动条 = dynamic_cast<C_滚动条*>(self);
	if (!滚动条->m_拖放阻止鼠标进出事件) {
		滚动条->m_滑块->m_ColorA.m_颜色.a = S_UI主题::uic_滚动条按钮.a;
		滚动条->m_更新绘制属性 = true;
	}
	
	
	return E_事件是否传递::e_事件传递_终止;
}

static void f_单向滚动条布局(C_Widget* r, C_Widget** w, uint32 num) {
	C_滚动条* 滚动条 = dynamic_cast<C_滚动条*>(r);
	
	float32 滑块位置比 = 滚动条->f_从绑定部件更新滑块();

	float32 映射值范围 = (滚动条->m_映射值范围 * 滚动条->m_值缩放比例);

	switch (滚动条->m_排列方向) {
		case E_方向::e_横向: {
			float32 滚动条长度 = max(滚动条->m_Size.x, 滚动条->m_Size.y);
			映射值范围 = max(映射值范围, 滚动条长度);

			float32 滑块大小 = max(滚动条长度 / 映射值范围 * 滚动条长度, 滚动条->m_Size.y);
			滚动条->m_滑块->f_setSize({滑块大小, 滚动条->m_Size.y});

			float32 滑块宽度 = 滚动条长度 - 滑块大小;
			滚动条->m_滑块->f_setX(滑块位置比 * 滑块宽度);
			return ;
		}

		case E_方向::e_纵向: {
			float32 滚动条高度 = max(滚动条->m_Size.y, 滚动条->m_Size.x);
			映射值范围 = max(映射值范围, 滚动条高度);

			float32 滑块大小 = max(滚动条高度 / 映射值范围 * 滚动条高度, 滚动条->m_Size.x);
			滚动条->m_滑块->f_setSize({滚动条->m_Size.x, 滑块大小});

			float32 滑块高度 = 滚动条高度 - 滑块大小;
			滚动条->m_滑块->f_setY(滑块位置比 * 滑块高度);
			return ;
		}
	}

}

C_滚动条::C_滚动条(S_UI渲染环境& ctx, E_方向 dir, C_Widget* 按钮[3]) : C_Widget(&ctx), m_排列方向(dir) {
	m_颜色A = S_UI主题::uic_滚动条;
	m_ColorA.m_颜色 = S_UI主题::uic_滚动条;

	m_滑块位置比 = 0;
	m_值缩放比例 = 1.0;
	m_值区间 = { 0,1 };
	
	m_滑块自适应大小 = false;
	m_映射值范围 = 1;
	m_映射位置 = nullptr;

	mf_滑块滚动回调 = nullptr;
	mf_布局	= f_单向滚动条布局;
	mf_鼠标进入 = on_单向滚动条鼠标进入;
	mf_鼠标离开 = on_单向滚动条鼠标离开;

	if (按钮) {
		for (uint8 i = 0; i < 3; ++i) {
			if (按钮[i]) {
				//f_添加子组件(按钮[i]);
			}
		}
	}

	m_滑块 = new C_Widget(&ctx);
	m_滑块->m_ColorA.m_颜色 = S_UI主题::uic_滚动条按钮;
	m_滑块->mf_拖拽 = on_数值滚动条手柄拖动;
	m_滑块->mf_开始拖拽 = on_数值滚动条手柄开始拖拽;
	m_滑块->mf_结束拖拽 = on_数值滚动条手柄结束拖拽;
	m_滑块->mf_鼠标按键按下;
	m_滑块->m_ColorA = S_2D颜色包(S_UI主题::uic_滚动条按钮);
	
	f_添加子组件(m_滑块);
}

C_滚动条::~C_滚动条() {
}

float32 C_滚动条::f_getValue() {

	return float32();
}

void C_滚动条::f_滚动滑块(float32 d) {
}

float32 C_滚动条::f_值手柄位置() {
	//m_Size
	float32 手柄长度 = m_值区间.y - m_值区间.x;

	switch (m_排列方向) {
	case E_方向::e_横向:
		手柄长度 = (m_Size.x - m_Size.y) / 手柄长度;
		return DEF_Min(m_Size.y, 手柄长度) * m_Size.x;

	case E_方向::e_纵向:
		手柄长度 = (m_Size.y - m_Size.x) / 手柄长度;
		return DEF_Min(m_Size.x, 手柄长度) * m_Size.y;
	}

	return 手柄长度;
}

void C_滚动条::f_计算绑定的值(float32 滚动条在条中比例) {
	m_滑块位置比 = 滚动条在条中比例;
	if (m_映射位置) {
		//if ((*m_映射位置)) {
		//
		//}
		switch (m_排列方向) {
			case E_方向::e_横向: {
				(*m_映射位置) = -(m_映射值范围 - m_Size.y * m_值缩放比例) * m_滑块位置比;
				break;
			}
			case E_方向::e_纵向: {
				(*m_映射位置) = -(m_映射值范围 - m_Size.y * m_值缩放比例) * m_滑块位置比;
				break;
			}
		}
	}
	//std::cout << "(*m_映射位置) = " << (*m_映射位置) << "  " << m_滑块位置比 << std::endl;
}

float32 C_滚动条::f_从绑定部件更新滑块() {
	if (m_映射位置) {
		
		switch (m_排列方向) {
			case E_方向::e_横向: {
				m_滑块位置比 = fabs(*m_映射位置) / (m_映射值范围 - m_Size.x * m_值缩放比例);
				break;
			}

			case E_方向::e_纵向: {
				m_滑块位置比 = fabs(*m_映射位置) / (m_映射值范围 - m_Size.y * m_值缩放比例);
				break;
			}
		}

		m_滑块位置比 = min(m_滑块位置比, 1);
	}
	
	return m_滑块位置比;
}

C_Widget* f_ui_创建滚动条(S_UI渲染环境& ctx, E_方向 方向) {
	auto box = new C_滚动条(ctx, 方向);

	return box;
}

void f_ui_滚动条绑定属性(C_Widget* self, float32* val, float32 edge) {
	C_滚动条* box = dynamic_cast<C_滚动条*>(self);
	assert(box);
	box->f_映射值指针(val, edge);
}

void f_ui_滚动条更新属性(C_Widget* self) {
	C_滚动条* box = dynamic_cast<C_滚动条*>(self);
	assert(box);
	box->f_从绑定部件更新滑块();
}

//void f_ui_更新滚动条(C_Widget* self) {
//	C_滚动条* box = dynamic_cast<C_滚动条*>(self);
//	assert(box);
//	box->f_从绑定部件更新滑块();
//}






S_双向滚动条::S_双向滚动条(float32 厚度, C_Widget* 父部件, S_UI渲染环境& ctx, C_Widget* 按钮[2]) {
	m_V = new C_滚动条(ctx, E_方向::e_纵向);
	m_H = new C_滚动条(ctx, E_方向::e_横向);

	m_V->f_setSize({ 厚度 , 厚度 });
	m_H->f_setSize({ 厚度 , 厚度 });

	父部件->f_添加子组件(m_V);
	父部件->f_添加子组件(m_H);
}

S_双向滚动条::~S_双向滚动条() {
	
}

std::vector<uint16> f_draw_双向滚动条(C_Widget* 部件, S_2D画布* 画布, float32 厚度) {
	return {};
}












static void on_Vec绘制(C_Widget* self, S_2D画布* 画布) {
	C_Vec& box = *(C_Vec*)(self);

}

static void on_Vec变换(C_Widget* self) {
	C_Vec* v = (C_Vec*)(self);
	auto e = self->f_get更新组件();
}

static void on_Vec布局(C_Widget* r, C_Widget** w, uint32 num) {
	C_Vec* vec = dynamic_cast<C_Vec*>(r);

	vec2 loc = {};
	vec2 size = r->m_Size;
	
	if (num) {
		switch (vec->m_方向) {
			case E_方向::e_横向:
				f_HBOX布局({0, 0}, size, w, num);
				break;
			case E_方向::e_纵向:
				f_VBOX布局({0, 0}, size, w, num);
				break;
			default:
				break;
		}
	}
}

static bool f_vec部件开启编辑(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_Vec* vec = dynamic_cast<C_Vec*>(self);
}
static void on_vec编辑框当前输入(C_Widget* self, std::wstring& text) {
	C_Vec* vec = dynamic_cast<C_Vec*>(self);
}
static void on_vec编辑框输入完成(C_Widget* self) {
	C_Vec* vec = dynamic_cast<C_Vec*>(self);
}

static void on_Vec_PropUpdate(S_Props& prop) {
	((C_Vec*)prop.m_UI->m_部件)->m_更新绘制属性 = true;
}


C_Vec::C_Vec(E_方向 dir, S_UI渲染环境& ctx) : C_Widget(&ctx){
	m_Type = E_WidgetType::t_矢量;
	m_方向 = dir;
	mf_布局 = on_Vec布局;

	m_颜色A = S_UI主题::uic_值编辑框背景;
	m_颜色B = S_UI主题::uic_值编辑框边;
	m_ColorA.m_颜色 = S_UI主题::uic_值编辑框背景;

	m_标签 = { L"x:", L"y:", L"z:", L"w:" };

	f_切换布局方向(m_方向);
}

C_Vec::~C_Vec() {

}

void C_Vec::f_切换布局方向(E_方向 方向) {
	m_方向 = 方向;

	if (m_子组件.size() >= 2) {
		if (m_方向 == E_方向::e_纵向) {
			((C_数值编辑框*)m_子组件[0])->m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面上圆角矩形;
			((C_数值编辑框*)(m_子组件.back()))->m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面下圆角矩形;
		}
		else {
			((C_数值编辑框*)m_子组件[0])->m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面左圆角矩形;
			((C_数值编辑框*)(m_子组件.back()))->m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面右圆角矩形;
		}
	}
}

void C_Vec::f_bind属性(S_Props& prop) {
	C_Widget::f_bind属性(prop);
	f_widget_remove所有子部件(this, false);

	float32 h = 24 * m_UIctx->m_DPI * m_自定义属性.m_值元素个数;

	for (uint8 i = 0; i < prop.m_值元素个数; ++i) {
		C_数值编辑框* box = new C_数值编辑框(*m_UIctx, i);
		box->m_是否延展 = {true, true};
		box->m_间隔宽度 = 1;
		box->m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面矩形;

		box->m_实例ID = i;
		box->m_标签 = m_标签[i];
		f_添加子组件(box);

		h += 24 * m_UIctx->m_DPI;
	}
	f_setH(h);
	f_切换布局方向(m_方向);


	auto e = f_get更新组件();
	for (uint8 i = 0; i < prop.m_值元素个数; ++i) {
		switch (prop.m_Type) {
			case E_值类型::e_Type_RGB:
			case E_值类型::e_Type_Vec2:
			case E_值类型::e_Type_Vec3:
			case E_值类型::e_Type_Vec4:{
				float32* v = ((float32*)prop.m_Value);
				dynamic_cast<C_数值编辑框*>(e.m_W[i])->m_Text = f_浮点数值转宽字符串(v[i]);
				break;
			}
			case E_值类型::e_Type_uVec2:
			case E_值类型::e_Type_uVec3:
			case E_值类型::e_Type_uVec4:
				dynamic_cast<C_数值编辑框*>(e.m_W[i])->m_Text = f_整数值转宽字符串(((uint32*)prop.m_Value)[i]);
				break;

			case E_值类型::e_Type_iVec2:
			case E_值类型::e_Type_iVec3:
			case E_值类型::e_Type_iVec4:
				dynamic_cast<C_数值编辑框*>(e.m_W[i])->m_Text = f_整数值转宽字符串(((int32*)prop.m_Value)[i]);
				break;
			default:
				break;
		}

		e.m_W[i]->f_bind属性(prop);
	}
	
}

void C_Vec::f_属性更新到组件() {
	for (auto& e : m_子组件) {
		e->f_属性更新到组件();
	}
}


void f_ui_绑定vec编辑框属性(C_Widget* w, S_Props prop) {
	
}

void f_ui_刷新vec编辑框文本绘制(C_Widget* w) {
	if (w->f_get窗口管理()->m_当前独占操作文本框) return;

	auto* view = dynamic_cast<C_Vec*>(w);

	auto e = w->f_get更新组件();
	for (uint8 i = 0; i < view->m_自定义属性.m_值元素个数; ++i) {
		switch (view->m_自定义属性.m_Type) {
			case E_值类型::e_Type_RGB:
			case E_值类型::e_Type_Vec2:
			case E_值类型::e_Type_Vec3:
			case E_值类型::e_Type_Vec4: {
				float32* v = ((float32*)view->m_自定义属性.m_Value);
				dynamic_cast<C_数值编辑框*>(e.m_W[i])->m_Text = f_浮点数值转宽字符串(v[i]);
				break;
			}
			case E_值类型::e_Type_uVec2:
			case E_值类型::e_Type_uVec3:
			case E_值类型::e_Type_uVec4:
				dynamic_cast<C_数值编辑框*>(e.m_W[i])->m_Text = f_整数值转宽字符串(((uint32*)view->m_自定义属性.m_Value)[i]);
				break;

			case E_值类型::e_Type_iVec2:
			case E_值类型::e_Type_iVec3:
			case E_值类型::e_Type_iVec4:
				dynamic_cast<C_数值编辑框*>(e.m_W[i])->m_Text = f_整数值转宽字符串(((int32*)view->m_自定义属性.m_Value)[i]);
				break;
			default:
				break;
		}

		e.m_W[i]->m_更新绘制属性 = true;
	}

	
}


static void on_多选框绘制(C_Widget* self, S_2D画布* 画布) {
	C_多选框& box = *(C_多选框*)(self);

	//box.m_背景 = f_vg_drawConvexElement(画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	//box.m_图标 = f_vg_drawIco(画布, S_UI主题::ui_默认图标);
	//box.m_标签 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, u"雅黑");

	//box.m_焦点 = f_vg_drawConvexElement(画布, E_填充模式::e_填充面, E_图层混合模式::e_Screen);

}

static void on_多选框布局(C_Widget* self, C_Widget** w, uint32 num) {
	if (!num) return;
	C_多选框& box = *(C_多选框*)(self);

	vec2 loc = {};
	vec2 size = self->m_Size;


	uint32 选项数量 = box.m_Value.m_值元素个数;
	
	switch (box.m_Value.m_Type) {
		case E_值类型::e_Type_Bool_1D: {

			switch (box.m_方向) {
				case E_方向::e_横向:
					size -= 3;
					f_HBOX布局({ 1.5f, 1.5f }, size, w, 选项数量);
					break;
				case E_方向::e_纵向:
					//size -= 3;
					f_VBOX布局({ 0, 0 }, size, w, 选项数量);
					break;
				default:
					break;
			}

			break;
		}
		case E_值类型::e_Type_UI8位域枚举: {
			f_Layout_网格(self, w, num, 8, 1);
			break;
		}
		case E_值类型::e_Type_UI16_FlagBits: {
			f_Layout_网格(self, w, num, 8, 2);
			break;
		}
		case E_值类型::e_Type_UI32_FlagBits: {
			f_Layout_网格(self, w, num, 8, 4);
			break;
		}
		default:
			break;
	}
}

static void on_多选框变换(C_Widget* self) {
	C_多选框& box = *(C_多选框*)(self);
	//if(!box.m_焦点) return;
	auto ws = self->f_get更新组件();

	std::vector<S_GPU内存块*>	形状(box.m_Value.m_值元素个数 + 1);
	std::vector<S_2DConvexRect>	区域(box.m_Value.m_值元素个数 + 1);
	std::vector<S_2D颜色包>		颜色(box.m_Value.m_值元素个数 + 1);
	std::vector<vec2>			位置(box.m_Value.m_值元素个数 + 1);

	const float32 间隔 = box.m_UIctx->m_DPI * 4;
	const vec2 pos = box.m_Pos;

	switch (box.m_Value.m_Type) {
		case E_值类型::e_Type_Bool_1D: {
			auto e = f_prop_Bool_1D(box.m_Value);
			

			std::vector<S_2D图标> 图标属性(box.m_Value.m_值元素个数);
			
			for (uint32 i = 0; i < box.m_Value.m_值元素个数; ++i) {
				S_2DConvexRect rect{};
				//rect.offset = ws.m_W[i]->m_Pos;
				rect.size = ws.m_W[i]->m_Size;
				rect.radius = { 4,4 };

				if (e[i].m_Value) {
					颜色[i + 1] = S_UI主题::uic_焦点色;
				}
				else {
					颜色[i + 1] = ws.m_W[i]->m_颜色A;
				}

				区域[i+1] = rect;
				形状[i+1] = ws.m_W[i]->m_图元形状;


				
				auto 文本区域 = ws.m_W[i]->f_getRect(true);
				//float32 图标大小 = min(rect.size.x, rect.size.y);
				vec2 图标坐标;

				switch (box.m_方向) {
					case E_方向::e_横向: {
						//图标坐标 = rect.offset + rect.size * 0.5;
						break;
					}
					default: {
						//图标坐标.x = 图标大小 * 0.5;
						//图标坐标.y = rect.offset.y + rect.size.y * 0.5;

						//文本区域.offset.x += 图标大小 + 间隔;
						//文本区域.extent.x -= 图标大小;
						break;
					}
				}

				//uint32 icoUV = f_vg_get图标UV(self->m_画布, box.m_图标, e[i].m_ICO);
				//图标属性[i] = f_vg_2D图标(图标坐标, icoUV, S_UI主题::uic_文字颜色, 图标大小 * 0.9);

				
				if (box.m_是否绘制标题) {
					//f_vg_setLineText(self->m_画布, box.m_标签, e[i].m_Names, 文本区域, E_对齐方式::e_左对齐, S_UI主题::uic_文字颜色);
				}
			}
		
			//f_vg_setIco(box.m_画布, box.m_图标, 图标属性.size(), 图标属性.data());

			break;
		}

		default: {
			uint64 mask = 0;
			switch (box.m_Value.m_Type) {
				case E_值类型::e_Type_UI32_FlagBits: {
					mask = f_prop_UI32(box.m_Value);
					break;
				}
				//case E_值类型::e_Type_UI16位域枚举: {
				//	mask = f_prop_U16位域(box.m_Value);
				//	break;
				//}
				case E_值类型::e_Type_UI8位域枚举: {
					mask = f_prop_U8位域(box.m_Value);
					break;
				}
			}
			

			for (uint32 i = 0; i < ws.m_Num; ++i) {
				S_2DConvexRect rect{};
				rect.size = ws.m_W[i]->m_Size;
				rect.radius = { 4,4 };

				if (mask & (1 << i)) {
					颜色[i + 1] = S_UI主题::uic_焦点色;
				}
				else {
					颜色[i + 1] = ws.m_W[i]->m_颜色A;
				}

				区域[i + 1] = rect;
				形状[i + 1] = ws.m_W[i]->m_图元形状;
				位置[i + 1] = ws.m_W[i]->m_Pos + pos;
			}
			break;
		}
	}


	S_2DConvexRect rect{};
	rect.size = box.m_Size;
	rect.radius = { 4,4 };
	rect.AA_type = { 1, 0 };
	区域[0] = rect;
	形状[0] = box.m_图元形状;;
	位置[0] = pos;
	//f_vg_setElementRect(self->m_画布, box.m_背景, 形状.size(), 形状.data(), rects.data());
	
	f_vg_drawConvex(*box.m_背景, 形状.size(), 形状.data(), 区域.data());
	f_vg_tranform(*box.m_背景, 位置.size(), 位置.data());
	f_vg_color(*box.m_背景, 颜色.size(), 颜色.data());
}

static E_事件是否传递 on_鼠标进入项(C_Widget* self, const S_鼠标& 鼠标) {
	C_多选框& box = *(C_多选框*)(self->m_父部件);

	S_2DConvexRect rect;
	//rect.offset = self->m_Pos;
	//rect.size = self->m_Size;
	rect.radius = { 4,4 };
	rect.AA_type = { f_PackData4X8({50,50,50,255}), 0};
	
	//f_vg_setElementRect(box.m_画布, box.m_焦点, 1, &self->m_图元形状, &rect);

	return E_事件是否传递::e_事件传递_继续;
}
static E_事件是否传递 on_鼠标离开项(C_Widget* self, const S_鼠标& 鼠标) {
	C_多选框& box = *(C_多选框*)(self->m_父部件);

	S_2DConvexRect rect;
	//rect.offset = self->m_Pos;
	//rect.size = self->m_Size;
	rect.radius = { 4,4 };
	rect.AA_type = { f_PackData4X8({0,0,0,0}), 0 };

	//f_vg_setElementRect(box.m_画布, box.m_焦点, 1, &self->m_图元形状, &rect);
	
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_鼠标离开多选框(C_Widget* self, const S_鼠标& 鼠标) {
	C_多选框& box = *(C_多选框*)(self);

	S_2DConvexRect rect;
	//rect.offset = self->m_Pos;
	//rect.size = self->m_Size;
	rect.radius = { 4,4 };
	rect.AA_type = { f_PackData4X8({100,100,100,255}), 0 };

	//f_vg_setElementRect(box.m_画布, box.m_焦点, 1, &self->m_图元形状, &rect);
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_鼠标点击项(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_多选框& box = *(C_多选框*)(self->m_父部件);

	switch (box.m_Value.m_Type) {
		case E_值类型::e_Type_Bool_1D: {
			auto e = f_prop_Bool_1D(box.m_Value);
			e[self->m_实例ID].m_Value = !(e[self->m_实例ID].m_Value);
			break;
		}
		case E_值类型::e_Type_UI32_FlagBits: {
			auto e = f_prop_UI32(box.m_Value);

			if (e & (1 << self->m_实例ID)) {
				f_prop_UI32(box.m_Value) &= ((1 << self->m_实例ID) ^ 0xffffffff);
			}
			else {
				f_prop_UI32(box.m_Value) |= (1 << self->m_实例ID);
			}
			break;
		}
		case E_值类型::e_Type_UI32Ops: {
			uint32& bf = f_prop_UI32位域枚举(box.m_Value);

			if (bf & (1 << self->m_实例ID)) {
				bf &= ((1 << self->m_实例ID) ^ 0xffffffff);
			}
			else {
				bf |= (1 << self->m_实例ID);
			}
			break;
		}
		case E_值类型::e_Type_UI8位域枚举: {
			uint8& bf = f_prop_U8位域(box.m_Value);

			if (bf & (1 << self->m_实例ID)) {
				bf &= ((1 << self->m_实例ID) ^ 0xff);
			}
			else {
				bf |= (1 << self->m_实例ID);
			}
			break;
		}
	}

	if (box.m_Value.m_UI->m_Update) {
		box.m_Value.m_UI->m_Update(box.m_Value);
	}
	box.m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_终止;
}

C_多选框::C_多选框(E_方向 dir, S_UI渲染环境& ctx) : C_Widget(&ctx) {
	m_Type = E_WidgetType::t_多选框;

	m_背景 = 0;
	m_标签 = 0;
	m_图标 = 0;

	mf_布局	= on_多选框布局;
	mf_绘制	= on_多选框绘制;
	mf_变换	= on_多选框变换;
	
	mf_鼠标离开 = on_鼠标离开多选框;

	m_颜色A = S_UI主题::uic_深灰;
	m_ColorA.m_颜色 = S_UI主题::uic_深灰;
	m_方向 = dir;
	
	
	m_是否绘制图标 = true;
	m_是否绘制标题 = true;

}

C_多选框::~C_多选框() {
}

void C_多选框::f_绑定数据(S_Props& prop) {
	uint32 num = m_子组件.size();
	m_Value = prop;

	uint32 元素个数 = 0;
	switch (m_Value.m_Type) {
		case E_值类型::e_Type_Bool_1D: {
			元素个数 = prop.m_值元素个数;
			break;
		}
		case E_值类型::e_Type_UI32_FlagBits: {
			元素个数 = 32;
			m_间隔宽度 = 2;
			break;
		}
		case E_值类型::e_Type_UI8位域枚举: {
			元素个数 = 32;
			m_间隔宽度 = 2;
			break;
		}
	}

	if (prop.m_值元素个数 <= 0) {
		switch (m_Value.m_Type) {
			case E_值类型::e_Type_Bool_1D: 元素个数 = prop.m_值元素个数; break;

			case E_值类型::e_Type_UI8位域枚举: 元素个数 = 8; break;
			case E_值类型::e_Type_UI16_FlagBits: 元素个数 = 16; break;
			case E_值类型::e_Type_UI32_FlagBits: 元素个数 = 32; break;
			case E_值类型::e_Type_UI64_FlagBits: 元素个数 = 64; break;
			default:
				元素个数 = 1;
				break;
		}
	}
	else {
		元素个数 = prop.m_值元素个数;
	}


	if (num > 元素个数) {
		f_widget_remove区间子组件(this, 元素个数, num);
	}
	else {
		for (uint32 i = num; i < 元素个数; ++i) {
			C_Widget* w = new C_Widget();
			w->mf_鼠标进入 = on_鼠标进入项;
			w->mf_鼠标离开 = on_鼠标离开项;
			w->mf_鼠标点击 = on_鼠标点击项;
			w->m_是否延展.x = true;
			w->m_是否延展.y = true;
			w->m_间隔宽度 = 1.5;
			w->m_实例ID = i;
			w->m_颜色A = S_UI主题::uic_按钮背景;
			f_添加子组件(w);
		}
	}

	auto e = f_get更新组件();

	uint64 mask = 0;
	switch (m_Value.m_Type) {
		case E_值类型::e_Type_UI8位域枚举: {
			mask = f_prop_U8位域(m_Value);
			break;
		}
		case E_值类型::e_Type_UI16_FlagBits:
		case E_值类型::e_Type_UI32_FlagBits:
		case E_值类型::e_Type_UI64_FlagBits:
			mask = f_prop_UI32(m_Value);
			break;

		case E_值类型::e_Type_UI32Ops:
			mask = f_prop_UI32位域枚举(m_Value);
			break;
	}

	for (uint32 i = 0; i < 元素个数; ++i) {
		e.m_W[i]->m_实例ID = i;

		if (mask & (1 << i)) {
			//e.m_W[i]->m_颜色A = S_UI主题::uic_菜单焦点色;
		}
	}

	
}



C_Widget* f_ui_创建多选框(S_UI渲染环境& ctx, E_方向 绘制方向, uint32 选项数量) {
	C_多选框* box = new C_多选框(绘制方向, ctx);
	return box;
}

void f_ui_bind多选框属性(C_Widget* self, S_Props& p, E_方向 方向) {
	assert(dynamic_cast<C_多选框*>(self));
	((C_多选框*)self)->f_绑定数据(p);
	((C_多选框*)self)->m_方向 = 方向;

	auto e = self->f_get更新组件();

	for (uint32 i = 0; i < e.m_Num; ++i) {
		e.m_W[i]->m_图元形状 = &S_2D画布::g预设_矩形;
	}


	switch (p.m_Type) {
		case E_值类型::e_Type_Bool_1D: {
			if (方向 == E_方向::e_横向) {
				e.m_W[0]->m_图元形状 = &S_2D画布::g预设_左圆角矩形;
				e.m_W[e.m_Num - 1]->m_图元形状 = &S_2D画布::g预设_右圆角矩形;
			}
			else {
				e.m_W[0]->m_图元形状 = &S_2D画布::g预设_上圆角矩形;
				e.m_W[e.m_Num - 1]->m_图元形状 = &S_2D画布::g预设_下圆角矩形;
			}
			break;
		}
		case E_值类型::e_Type_UI32_FlagBits: {
			e.m_W[0]->m_图元形状 = &S_2D画布::g预设_左上圆角矩形;
			e.m_W[7]->m_图元形状 = &S_2D画布::g预设_右上圆角矩形;
			e.m_W[24]->m_图元形状 = &S_2D画布::g预设_左下圆角矩形;
			e.m_W[31]->m_图元形状 = &S_2D画布::g预设_右下圆角矩形;
			break;
		}
		case E_值类型::e_Type_UI8位域枚举: {
			e.m_W[0]->m_图元形状 = &S_2D画布::g预设_左圆角矩形;
			e.m_W[7]->m_图元形状 = &S_2D画布::g预设_右圆角矩形;
			break;
		}
	}


	if (e.m_Num > 1) {
		if (方向 == E_方向::e_横向) {
			e.m_W[0]->m_图元形状 = &self->m_UIctx->m_Ctx.m_几何图形->m_平面左圆角矩形;
			e.m_W[e.m_Num - 1]->m_图元形状 = &self->m_UIctx->m_Ctx.m_几何图形->m_平面右圆角矩形;
		}
		else {
			e.m_W[0]->m_图元形状 = &self->m_UIctx->m_Ctx.m_几何图形->m_平面上圆角矩形;
			e.m_W[e.m_Num - 1]->m_图元形状 = &self->m_UIctx->m_Ctx.m_几何图形->m_平面下圆角矩形;
		}
	}
}








static vec2 g节点鼠标局部位置 = { 0,0 };
static float32 g控制点拾取大小 = 8;



static E_事件是否传递 on_曲线编辑视口准备拖动(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	g节点鼠标局部位置 = f_widget_get鼠标局部位置(鼠标.gPos, self);
	std::cout<<self->m_实例ID<<std::endl;
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_曲线编辑视口拖动(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	C_curve编辑视口* box = static_cast<C_curve编辑视口*>(self->m_父部件);

	vec2 相对于开始拖拽时鼠标相对组件偏移 = f_widget_get鼠标局部位置(鼠标.gPos, box);
	相对于开始拖拽时鼠标相对组件偏移.x -= g节点鼠标局部位置.x;
	相对于开始拖拽时鼠标相对组件偏移.y -= g节点鼠标局部位置.y;
	
	vec2 size = box->m_Size - g控制点拾取大小;
	if (相对于开始拖拽时鼠标相对组件偏移.x > size.x) 相对于开始拖拽时鼠标相对组件偏移.x = size.x;
	if (相对于开始拖拽时鼠标相对组件偏移.y > size.y) 相对于开始拖拽时鼠标相对组件偏移.y = size.y;
	if (相对于开始拖拽时鼠标相对组件偏移.x < 0) 相对于开始拖拽时鼠标相对组件偏移.x = 0;
	if (相对于开始拖拽时鼠标相对组件偏移.y < 0) 相对于开始拖拽时鼠标相对组件偏移.y = 0;
	
	self->f_setPos(相对于开始拖拽时鼠标相对组件偏移);

	vec2 相对偏移比例 = 相对于开始拖拽时鼠标相对组件偏移 / size;
	
	auto* curve = f_prop_2DCurve(box->m_Value);
	auto* point = f_an_get曲线点A(curve, self->m_实例ID);
	//std::cout<<self->m_实例ID<<std::endl;
	if (point) {
		相对偏移比例.y = 1.0 - 相对偏移比例.y;
		point->value = 相对偏移比例;
	}
	
	f_an_钳制曲线值排序(curve);
	f_an_钳制曲线自动控制点(curve);
	box->m_更新绘制属性 = true;

	return E_事件是否传递::e_事件传递_终止;
}

static bool on_曲线编辑视口结束拖放(C_Widget* self, C_Widget* 拾取的部件, S_拖放数据& data) {
	C_curve编辑视口* box = static_cast<C_curve编辑视口*>(self->m_父部件);

	if (!(self->m_开启渲染)) return true;

	auto* curve = f_prop_2DCurve(box->m_Value);

	//auto* point = f_an_get曲线点A(curve, self->m_实例ID);
	auto e = box->f_get更新组件();
	auto* point = f_an_get曲线点A(curve, self->m_实例ID);
	if (point && e.m_Num) {
		int32 id = f_an_移除曲线重合点(curve, point, 0.05);
		
		for (uint32 i = 0; i < e.m_Num; ++i) {
			if (e.m_W[i]->m_实例ID == id) {
				
				e.m_W[i]->m_开启渲染 = false;
				e.m_W[i]->f_setPos({ -1,-1 });
				e.m_W[i]->m_实例ID = -1;

				f_an_钳制曲线值排序(curve);
				f_an_钳制曲线自动控制点(curve);
				break;
			}
		}
	}

	f_prop_采样曲线拷贝到GPU(box->m_Value);
	//f_buf_gresize(box->m_Value.m_GPU缓存[0], curve->count);
	//for (uint32 i = 0; i < curve->count; ++i) {
	//	f_buf_曲线段_at(box->m_Value.m_GPU缓存[0], i) = curve->point[i];
	//}
	//f_buf_uVec2_at(box->m_Value.m_GPU缓存[1]) = { uint32(box->m_Value.m_GPU缓存[0].m_Mem.m_偏移), box->m_Value.m_GPU缓存[0].m_Mem.m_大小 };
	return true;
}

static E_事件是否传递 on_曲线编辑视口控制点鼠标进入(C_Widget* self, const S_鼠标& 轮值) {
	C_curve编辑视口* box = static_cast<C_curve编辑视口*>(self->m_父部件);
	self->m_颜色A = { 255,255,200,255 };
	box->m_更新绘制属性 = true;
	std::cout<<self->m_实例ID<<std::endl;
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_曲线编辑视口控制点鼠标移出(C_Widget* self, const S_鼠标& 轮值) {
	C_curve编辑视口* box = static_cast<C_curve编辑视口*>(self->m_父部件);
	self->m_颜色A = { 150,150,150,255 };
	box->m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_继续;
}


static C_Widget* f_添加钳制曲线控制点组件(C_Widget* self) {
	C_Widget* 控制点 = new C_Widget(self->m_UIctx);
	控制点->mf_开始拖拽 = on_曲线编辑视口准备拖动;
	控制点->mf_拖拽 = on_曲线编辑视口拖动;
	控制点->mf_结束拖拽 = on_曲线编辑视口结束拖放;
	控制点->mf_鼠标进入 = on_曲线编辑视口控制点鼠标进入;
	控制点->mf_鼠标离开 = on_曲线编辑视口控制点鼠标移出;
	控制点->m_开启渲染 = true;

	控制点->f_setSize({ g控制点拾取大小, g控制点拾取大小 });
	self->f_添加子组件(控制点);
	return 控制点;
}


static E_事件是否传递 on_曲线编辑视口添加控制点(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_curve编辑视口* box = static_cast<C_curve编辑视口*>(self);
	vec2 位置 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	
	auto* curve = f_prop_2DCurve(box->m_Value);

	static S_Gpu曲线拾取计算* pick = new S_Gpu曲线拾取计算(box->m_UIctx->m_Ctx);

	vec2 size = box->m_Size - g控制点拾取大小;
	位置 = vec_Max(位置, { 0,0 });
	位置 = vec_Min(位置, size);

	vec2 点偏移 = size;
	点偏移.x = (g控制点拾取大小 * 0.5) / 点偏移.x;
	点偏移.y = (g控制点拾取大小 * 0.5) / 点偏移.y;

	vec2 相对偏移比例 = 位置;
	相对偏移比例 = 位置 / size;
	相对偏移比例 -= 点偏移;
	相对偏移比例.y = 1.0 - 相对偏移比例.y;
	
	auto e = self->f_get更新组件();
	uint32 已使用点数量 = 0;
	for (uint32 i = 0; i < e.m_Num; ++i) {
		if (e.m_W[i]->m_开启渲染) {
			++已使用点数量;
		}
	}

	if (已使用点数量 > 2) {
		float32 minDis = 100000000;
		int32 点ID = -1;
		for (uint32 i = 0; i < curve->count - 1; ++i) {
			for (uint32 j = 0; j <= 32; ++j) {
				float muse_to_center_dis = f_curve_cal_toLineCenterDis(curve->point[i], curve->point[i + 1], 相对偏移比例, j, 0.02);
				if (muse_to_center_dis < 0.02) {
					if (muse_to_center_dis < minDis) {
						minDis = muse_to_center_dis;
						点ID = i;
					}
				}
			}
		}
		if (点ID < 0) {
			return E_事件是否传递::e_事件传递_终止;
		}
	}
	C_Widget* 控制点 = nullptr;
	uint32 i = 0;
	for (; i < 已使用点数量; ++i) {
		if (e.m_W[i]->m_开启渲染 == false) {
			控制点 = e.m_W[i];
			控制点->m_开启渲染 = true;
			控制点->m_实例ID = 已使用点数量;
			box->m_更新绘制属性 = true;
			break;
		}
	}
	if (!控制点) {
		控制点 = f_添加钳制曲线控制点组件(self);
		控制点->m_实例ID = 已使用点数量;
		控制点->m_开启渲染 = true;
	}
	控制点->f_setPos(位置);
	
	

	f_an_添加钳制曲线点(curve, 相对偏移比例, { 0,0 }, { 0,0 }, 控制点->m_实例ID);
	f_an_钳制曲线值排序(curve);
	f_an_钳制曲线自动控制点(curve);

	f_prop_采样曲线拷贝到GPU(box->m_Value);
	//f_buf_gresize(box->m_Value.m_GPU缓存[0], curve->count);
	//for (i = 0; i < curve->count; ++i) {
	//	f_buf_曲线段_at(box->m_Value.m_GPU缓存[0], i) = curve->point[i];
	//}
	//f_buf_uVec2_at(box->m_Value.m_GPU缓存[1]) = { uint32(box->m_Value.m_GPU缓存[0].m_Mem.m_偏移), box->m_Value.m_GPU缓存[0].m_Mem.m_大小 };

	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_曲线采样框鼠标移动(C_Widget* self, const ivec4& value) {
	C_curve编辑视口* box = static_cast<C_curve编辑视口*>(self);

	vec2 位置 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);

	const auto* curve = f_prop_2DCurve(box->m_Value);

	vec2 size = box->m_Size - g控制点拾取大小;
	位置 = vec_Max(位置, { 0,0 });
	位置 = vec_Min(位置, size);

	vec2 点偏移 = size;
	点偏移.x = (g控制点拾取大小 * 0.5) / 点偏移.x;
	点偏移.y = (g控制点拾取大小 * 0.5) / 点偏移.y;

	vec2 相对偏移比例 = 位置;
	相对偏移比例 = 位置 / size;
	相对偏移比例 -= 点偏移;
	相对偏移比例.y = 1.0 - 相对偏移比例.y;


	int32 minDisID = -1;
	if (curve->count > 1) {
		float32 minDis = 100000000;
		
		for (uint32 i = 0; i < curve->count; ++i) {

			for (uint32 j = 0; j <= 32; ++j) {
				float muse_to_center_dis = f_curve_cal_toLineCenterDis(curve->point[i], curve->point[i + 1], 相对偏移比例, j, 0.02);

				if (muse_to_center_dis < 0.02) {
					if (muse_to_center_dis < minDis) {
						minDis = muse_to_center_dis;
						minDisID = i;
					}
				}
			}
		}
	}
	if (minDisID >= 0) {
		box->m_线颜色 = { 30,30,30,255 };
	}
	else {
		box->m_线颜色 = { 10,10,10,255 };
	}


	box->m_Value.m_UI->m_Update(box->m_Value);
	//std::cout << "minDis = " << minDis << " " << minDisID << " " << minDisIDA << std::endl;
	return E_事件是否传递::e_事件传递_终止;
}

static void on_曲线编辑视口布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_curve编辑视口* box = static_cast<C_curve编辑视口*>(self);

	auto* curve = f_prop_2DCurve(box->m_Value);
	if(curve->count > num) return;

	for (uint32 i = 0; i < curve->count; ++i) {
		auto& 曲线点 = curve->point[i];
		
		vec2 pos = 曲线点.value;
		pos.y = 1.0 - pos.y;
		pos.x *= self->m_Size.x - g控制点拾取大小;
		pos.y *= self->m_Size.y - g控制点拾取大小;
		//std::cout << "相对于开始拖拽时鼠标相对组件偏移.x = " << pos.x << std::endl;
		w[曲线点.ID_Color.x]->f_setPos(pos);
		w[曲线点.ID_Color.x]->m_开启渲染 = true;
	}

}

static void on_曲线编辑视口绘制(C_Widget* self, S_2D画布* 画布) {
	C_curve编辑视口* box = static_cast<C_curve编辑视口*>(self);

	//box->m_点绘制.m_属性 = f_vg_gen属性(画布);
	//
	//box->m_曲线绘制.m_属性 = f_vg_gen属性(画布);
	//box->m_曲线绘制.f_Draw(画布, box->m_曲线绘制.m_属性);
	//
	//S_凸边图元 图元 = {};
	//图元.属性 = f_vg_get属性指针(画布, box->m_点绘制.m_属性);
	//box->m_点绘制.f_Draw(画布, 图元, E_笔刷类型::e_单色填充);

}

static void on_曲线编辑视口变换(C_Widget* self) {
	C_curve编辑视口* box = static_cast<C_curve编辑视口*>(self);
	auto e = self->f_get更新组件();
	//vec2 loc = { 4, 4 };
	vec2 size = self->m_Size - g控制点拾取大小;
	const auto* curve = f_prop_2DCurve(box->m_Value);


	//S_2D_PanelAttr 属性;
	//属性.m_Offset = {};
	//属性.m_Scale = {1,1};
	//属性.m_渐变数量 = 0;
	//属性.m_间隔 = 0;
	//f_vg_set属性(self->m_画布, box->m_点绘制.m_属性, 属性);
	//
	//
	//
	//属性.m_Offset = {};
	//属性.m_Scale = size;
	//属性.m_渐变数量 = curve->count - 2;
	//属性.m_间隔 = 0;
	//f_vg_set属性(self->m_画布, box->m_曲线绘制.m_属性, 属性);
	//
	//uint32 num = curve->count;
	//
	//box->m_点绘制.f_alloc(num);
	//box->m_曲线绘制.f_begin(num);
	//
	//vec2 点偏移 = size;
	//点偏移.x = (g控制点拾取大小 * 0.5) / 点偏移.x;
	//点偏移.y = (g控制点拾取大小 * 0.5) / 点偏移.y;
	//for(uint32 i = 0; i< num; ++i){
	//	auto 曲线点 = curve->point[i];
	//
	//	曲线点.value.y = 1.0 - 曲线点.value.y;
	//	曲线点.L_point.y = 1.0 - 曲线点.L_point.y;
	//	曲线点.R_point.y = 1.0 - 曲线点.R_point.y;
	//	
	//	
	//	
	//	mat3X2 Mat;
	//	Mat.row0 = 曲线点.value * size + 0.5f;
	//	Mat.row1 = { 6,6 };
	//	Mat.row2 = { S_UI主题::ui_面板圆角半径, 0 };
	//	box->m_点绘制.f_set单色填充(i, Mat, e.m_W[曲线点.ID_Color.x]->m_颜色A, S_Widget预设凸包图元::m_矩形);
	//	
	//	曲线点.value += 点偏移;
	//	曲线点.L_point += 点偏移;
	//	曲线点.R_point += 点偏移;
	//	曲线点.ID_Color.y = f_PackData4X8(box->m_线颜色);
	//	box->m_曲线绘制.f_setPoint(i, 曲线点);
	//
	//}
	//box->m_曲线绘制.f_end();
}

C_curve编辑视口::C_curve编辑视口(S_UI渲染环境& ctx) : C_Widget(&ctx) {
	mf_布局 = on_曲线编辑视口布局;
	mf_绘制 = on_曲线编辑视口绘制;
	mf_变换 = on_曲线编辑视口变换;

	mf_鼠标点击 = on_曲线编辑视口添加控制点;
	mf_鼠标移动 = on_曲线采样框鼠标移动;

	m_Value = {};
	m_临时曲线数据 = f_core_array_new(0, sizeof(S_CurvePoint2));

	m_线颜色 = { 10,10,10,255 };
}

C_curve编辑视口::~C_curve编辑视口(){
	f_core_array_free(m_临时曲线数据);
}



static void on_曲线采样框布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_曲线采样框* box = static_cast<C_曲线采样框*>(self);

	vec2 loc = { 4, 4 };
	vec2 size = self->m_Size;
	size.x -= 8;
	size.y -= 34;

	box->ui曲线视口->f_setPos(loc);
	box->ui曲线视口->f_setSize(size);


	loc.y = self->m_Size.y - 24;
	size.y = 20;
	box->ui当前选中控制点->f_setPos(loc);
	box->ui当前选中控制点->f_setSize(size);

}

static void on_曲线采样框绘制(C_Widget* self, S_2D画布* 画布) {
	C_曲线采样框* box = static_cast<C_曲线采样框*>(self);

	
}

static void on_曲线采样框变换(C_Widget* self) {
	C_曲线采样框* box = static_cast<C_曲线采样框*>(self);

	auto ws = self->f_get更新组件();
	

}

C_曲线采样框::C_曲线采样框(S_UI渲染环境& ctx) : C_Widget(&ctx) {
	mf_布局 = on_曲线采样框布局;
	mf_绘制 = on_曲线采样框绘制;
	mf_变换 = on_曲线采样框变换;

	f_setSize({ 256,150 });
	
	m_当前选中控制点 = f_alloc_Vec2Prop(nullptr, u"控制点");
	f_prop_Vec2(m_当前选中控制点) = { 0,0 };

	ui当前选中控制点 = new C_Vec(E_方向::e_横向, ctx);
	ui当前选中控制点->f_bind属性(m_当前选中控制点);
	ui曲线视口 = new C_curve编辑视口(ctx);

	f_添加子组件(ui曲线视口);
	f_添加子组件(ui当前选中控制点);
}

C_曲线采样框::~C_曲线采样框() {
}

C_Widget* f_ui_创建曲线采样器(S_UI渲染环境& ctx) {
	C_曲线采样框* box = new C_曲线采样框(ctx);

	return box;
}

void f_ui_曲线采样器绑定属性数据(C_Widget* self, S_Props& prop) {
	C_curve编辑视口* curve_view = static_cast<C_曲线采样框*>(self)->ui曲线视口;
	curve_view->m_Value = prop;

	auto* curve = f_prop_2DCurve(curve_view->m_Value);
	vec2 size = curve_view->m_Size - g控制点拾取大小;
	uint32 num = curve->count;

	
	f_widget_remove所有子部件(curve_view, false);
	
	for (uint32 i = 0; i < num; ++i) {
		C_Widget* 控制点 = f_添加钳制曲线控制点组件(curve_view);
		
		控制点->m_开启渲染 = true;
		控制点->m_实例ID = i;
		控制点->f_setPos(curve->point[i].value * size);
		curve->point[i].ID_Color.x = i;

		//f_buf_曲线段_at(prop.m_GPU缓存[0], i) = curve->point[i];
	}
	//f_buf_uVec2_at(prop.m_GPU缓存[1]) = { uint32(prop.m_GPU缓存[0].m_Mem.m_偏移), prop.m_GPU缓存[0].m_Mem.m_大小 };
	if (prop.m_GPU缓存[0].m_Buf) f_bm_resize(prop.m_GPU缓存[0], num);
	f_prop_采样曲线拷贝到GPU(curve_view->m_Value);


	curve_view->m_更新绘制属性 = true;
	self->m_更新绘制属性 = true;
	
}





C_多曲线编辑框::C_多曲线编辑框(S_UI渲染环境& ctx) {
}

C_多曲线编辑框::~C_多曲线编辑框() {
}





S_Gpu曲线拾取计算::S_Gpu曲线拾取计算(S_设备环境& ctx) {
	std::vector<S_着色器创建参数> 参数配置;

	参数配置 = {
		{DEF_BINDING_WIDGET_CurvePoint, E_着色阶段::e_计算着色, E_板载缓存类型::e_SSBO},
		{DEF_BINDING_WIDGET_CurvePick, E_着色阶段::e_计算着色, E_板载缓存类型::e_SSBO},
		{DEF_BINDING_WIDGET_CurvePickID, E_着色阶段::e_计算着色, E_板载缓存类型::e_SSBO},
	};

	m_GpuCtx = f_df_创建并行计算(ctx, S_引擎配置::m_UI着色器文件根路径 + "UI曲线拾取.spv", 参数配置);

	//m_相交数据 = f_buf_create板载缓存(*m_GpuCtx->m_Ctx, E_板载缓存类型::e_SSBO, sizeof(vec2));
	//S_Gpu实例拾取信息 拾取属性参数 = { mat, s, dir };S_CurvePick
	//f_buf_fill板载缓存(拾取属性, &拾取属性参数, sizeof(S_GpuPick));
	m_参数元素[0] = nullptr;
	m_参数元素[1] = f_buf_create板载缓存(m_GpuCtx->m_Ctx, sizeof(S_CurvePick), E_板载缓存类型::e_SSBO, 1);
	m_参数元素[2] = f_buf_create板载缓存(m_GpuCtx->m_Ctx, E_板载缓存类型::e_SSBO, sizeof(vec2));
	//m_参数元素[2] = m_相交数据;

	m_布局位置[0] = DEF_BINDING_WIDGET_CurvePoint;
	m_布局位置[1] = DEF_BINDING_WIDGET_CurvePick;
	m_布局位置[2] = DEF_BINDING_WIDGET_CurvePickID;

}

int32 S_Gpu曲线拾取计算::f_run(S_板载缓存* 曲线控制点, vec2 拾取坐标, float32 最小距离) {
	if (曲线控制点->m_Size < 2) return -1;

	uvec3 dim = { 1,1,1 };
	m_参数元素[0] = 曲线控制点;

	dim.x = 曲线控制点->m_Size - 1;

	S_CurvePick* pick = f_buf_map板载缓存<S_CurvePick>(m_参数元素[1]);
	pick->pick_coord = 拾取坐标;
	pick->pick_dis.x = 最小距离;
	f_buf_unmap板载缓存(m_参数元素[1]);


	f_buf_resize(m_参数元素[2], 曲线控制点->m_Size);


	f_setGPU参数布局(m_GpuCtx, { m_参数元素, m_布局位置, nullptr, nullptr, 3, 0 });

	f_GPU_run计算(m_GpuCtx, dim);

	vec2* 拾取距离 = f_buf_map板载缓存<vec2>(m_参数元素[2]);
	for (uint32 i = 0; i < dim.x; ++i) {
		std::cout << "拾取距离 = "<< i << " : " << 拾取距离[i].x << " " << 拾取距离[i].y << std::endl;
	}
	f_buf_unmap板载缓存(m_参数元素[2]);
	return int32();
}






static void on_数值信息框绘制(C_Widget* self, S_2D画布* 画布) {
	C_数值信息框& box = *(C_数值信息框*)(self);

	box.m_背景 = f_vg_genConvex((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	box.m_标签 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, S_UI主题::ui_默认字体);
	box.m_图标 = f_vg_genIco((*self), *画布, E_图层混合模式::e_Normal, E_填充模式::e_填充面);

}

static void on_数值信息框布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_数值信息框& box = *(C_数值信息框*)(self);

	vec2 loc = {};
	vec2 size = self->m_Size;

	uint32 选项数量 = box.m_Value.m_值元素个数;

}

static void on_数值信息框变换(C_Widget* self) {
	C_多选框& box = *(C_多选框*)(self);
	//if(!box.m_焦点) return;
	auto ws = self->f_get更新组件();

	std::vector<S_GPU内存块*>	形状(box.m_Value.m_值元素个数 + 1);
	std::vector<S_2DConvexRect>	区域(box.m_Value.m_值元素个数 + 1);
	std::vector<S_2D颜色包>		颜色(box.m_Value.m_值元素个数 + 1);
	std::vector<vec2>			位置(box.m_Value.m_值元素个数 + 1);

	const float32 间隔 = box.m_UIctx->m_DPI * 4;
	const vec2 pos = box.m_Pos;

	switch (box.m_Value.m_Type) {
		case E_值类型::e_Type_Bool_1D: {
			auto e = f_prop_Bool_1D(box.m_Value);


			std::vector<S_2D图标> 图标属性(box.m_Value.m_值元素个数);

			for (uint32 i = 0; i < box.m_Value.m_值元素个数; ++i) {
				S_2DConvexRect rect{};
				//rect.offset = ws.m_W[i]->m_Pos;
				rect.size = ws.m_W[i]->m_Size;
				rect.radius = { 4,4 };

				if (e[i].m_Value) {
					颜色[i + 1] = S_UI主题::uic_焦点色;
				}
				else {
					颜色[i + 1] = ws.m_W[i]->m_颜色A;
				}

				区域[i+1] = rect;
				形状[i+1] = ws.m_W[i]->m_图元形状;



				auto 文本区域 = ws.m_W[i]->f_getRect(true);
				//float32 图标大小 = min(rect.size.x, rect.size.y);
				vec2 图标坐标;

				switch (box.m_方向) {
					case E_方向::e_横向: {
						//图标坐标 = rect.offset + rect.size * 0.5;
						break;
					}
					default: {
						//图标坐标.x = 图标大小 * 0.5;
						//图标坐标.y = rect.offset.y + rect.size.y * 0.5;

						//文本区域.offset.x += 图标大小 + 间隔;
						//文本区域.extent.x -= 图标大小;
						break;
					}
				}

				//uint32 icoUV = f_vg_get图标UV(self->m_画布, box.m_图标, e[i].m_ICO);
				//图标属性[i] = f_vg_2D图标(图标坐标, icoUV, S_UI主题::uic_文字颜色, 图标大小 * 0.9);


				if (box.m_是否绘制标题) {
					//f_vg_setLineText(self->m_画布, box.m_标签, e[i].m_Names, 文本区域, E_对齐方式::e_左对齐, S_UI主题::uic_文字颜色);
				}
			}

			//f_vg_setIco(box.m_画布, box.m_图标, 图标属性.size(), 图标属性.data());

			break;
		}

		default: {
			uint64 mask = 0;
			switch (box.m_Value.m_Type) {
				case E_值类型::e_Type_UI32_FlagBits: {
					mask = f_prop_UI32(box.m_Value);
					break;
				}
												//case E_值类型::e_Type_UI16位域枚举: {
												//	mask = f_prop_U16位域(box.m_Value);
												//	break;
												//}
				case E_值类型::e_Type_UI8位域枚举: {
					mask = f_prop_U8位域(box.m_Value);
					break;
				}
			}


			for (uint32 i = 0; i < ws.m_Num; ++i) {
				S_2DConvexRect rect{};
				rect.size = ws.m_W[i]->m_Size;
				rect.radius = { 4,4 };

				if (mask & (1 << i)) {
					颜色[i + 1] = S_UI主题::uic_焦点色;
				}
				else {
					颜色[i + 1] = ws.m_W[i]->m_颜色A;
				}

				区域[i + 1] = rect;
				形状[i + 1] = ws.m_W[i]->m_图元形状;
				位置[i + 1] = ws.m_W[i]->m_Pos + pos;
			}
			break;
		}
	}


	S_2DConvexRect rect{};
	rect.size = box.m_Size;
	rect.radius = { 4,4 };
	rect.AA_type = { 1, 0 };
	区域[0] = rect;
	形状[0] = box.m_图元形状;;
	位置[0] = pos;
	//f_vg_setElementRect(self->m_画布, box.m_背景, 形状.size(), 形状.data(), rects.data());

	f_vg_drawConvex(*box.m_背景, 形状.size(), 形状.data(), 区域.data());
	f_vg_tranform(*box.m_背景, 位置.size(), 位置.data());
	f_vg_color(*box.m_背景, 颜色.size(), 颜色.data());
}

C_数值信息框::C_数值信息框(S_UI渲染环境& ctx) {
	mf_绘制 = on_数值信息框绘制;
	mf_布局 = on_数值信息框布局;
	mf_变换 = on_数值信息框变换;
}

C_数值信息框::~C_数值信息框() {
	
}



